package base.aqs.semaphore;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * @author chengzhang
 * 2021/9/9 11:15
 */
public class Semaphore01 {

    /**
     * Semaphore内部计数器是递增的，并且在一开始初始化Semaphore时可以指定一个初始值，并且不需要知道需要同步的线程个数，而是需要在同步的地方
     * 调用acquire方法指定需要同步的线程个数
     */
    public static Semaphore semaphore = new Semaphore(0);

    /**
     * 本案例中，信号量计数器的值为0.main函数中添加两个线程任务，每个线程内部调用信号量的release方法，相当于让计数器值递增1.
     * 最后在main线程里调用信号量的acquire方法，传参为2说明调用acquire方法的线程会一直阻塞，知道信号量的计数变为2才会返回。
     * 如果Semaphore构造函数传入参数为N,并且在M个线程中调用了该信号量的release方法，那么在调用acquire使M个线程同步时传递的参数应该是M+N
     */
    public static void main(String[] args) throws InterruptedException {

        //创建一个线程个数固定为2的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        //将线程A添加到线程池
        executorService.submit(() -> {
            try {
                System.out.println(Thread.currentThread() + "over");
                semaphore.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        //将线程B添加到线程池
        executorService.submit(() -> {
            try {
                System.out.println(Thread.currentThread() + "over");
                semaphore.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });


        //等待子线程执行完毕，返回
        semaphore.acquire(2);
        System.out.println("all child thread over!");
        //关闭线程池
        executorService.shutdown();
    }

}
